import json
import zlib
import httpx
import base64
import asyncio
import hashlib
from app.supply import get_timestamp, log
from random import choice
from fastapi import Request
from datetime import datetime
from urllib.parse import urlencode


neteStartIndex = 1000000  # 假设的起始索引
userAgentList = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Edge/91.0.864.48 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15",
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
    "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1",
]


# 获取 User-Agent
def get_user_agent():
    return choice(userAgentList)


current_time_millis = int(datetime.now().timestamp() * 1000)


def check_name(name1: str | None, name2: str | None) -> bool:
    """
    检查两个字符串是否相互包含（忽略大小写）

    :param name1: 第一个字符串，可能为 None
    :param name2: 第二个字符串，可能为 None
    :return: 如果任一字符串包含另一个字符串（忽略大小写），返回 True；否则返回 False
    """
    if name1 is None or name2 is None:
        return False

    # 将字符串转换为小写，避免大小写敏感问题
    lower_name1 = name1.lower()
    lower_name2 = name2.lower()

    # 检查相互包含关系
    return lower_name1 in lower_name2 or lower_name2 in lower_name1


def parse_time(time_str: str | None) -> int | None:
    """
    解析 yyyy-mm-dd 或 yyyy-mm 格式的时间字符串，返回时间戳（秒级）

    参数:
        time_str: 时间字符串，支持格式：yyyy-mm-dd、yyyy-mm、yyyy-mm-ddTHH:MM:SS

    返回:
        int: 时间戳（秒级），如果解析失败返回 None
    """
    if not time_str or not time_str.strip():
        return None

    time_str = time_str.strip()

    # 尝试的格式列表（按优先级排序）
    formats = [
        "%Y-%m-%d",  # 完整日期
        "%Y-%m",  # 年月
        "%Y-%m-%dT%H:%M:%S",  # ISO 格式
    ]

    for fmt in formats:
        try:
            # 解析字符串并返回时间戳
            dt = datetime.strptime(time_str, fmt)
            return int(dt.timestamp())
        except ValueError:
            continue

    return None


def join_list(items, key):
    # 假设 joinList 是一个已经定义的函数，用于将列表中的某个键的值连接成字符串
    # 这里仅作示例，具体实现请根据实际情况编写
    return "/".join(item[key] for item in items if key in item)


def signature_params(params: dict) -> str:
    # 对字典项按键排序并拼接成字符串
    sorted_params = sorted(params.items())
    data = "".join(f"{key}={value}" for key, value in sorted_params)

    secret = "NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt"
    # 拼接 secret + data + secret
    signature_data = f"{secret}{data}{secret}"

    # 计算 MD5 哈希并转换为大写
    md5_hash = hashlib.md5(signature_data.encode("utf-8")).hexdigest().upper()

    return md5_hash


async def retuen_null():
    return ""


async def get_qq_meta(request: Request, item: dict):
    client = request.app.state.client
    try:
        data = {
            "data": json.dumps(
                {
                    "comm": {"ct": 24, "cv": 0},
                    "songInfo": {
                        "module": "music.pf_song_detail_svr",
                        "method": "get_song_detail_yqq",
                        "param": {
                            "song_type": 0,
                            "song_id": item.get("id", 0),  # 使用get方法处理可选参数
                        },
                    },
                },
                ensure_ascii=False,
            )
        }
        response = await client.send(
            httpx.Request("GET", "https://u.y.qq.com/cgi-bin/musicu.fcg", params=data)
        )

        res = response.json()
        data = res["songInfo"]["data"]
        info = data["track_info"]
        album_id = info["album"]["id"]

        return {
            "title": info.get("name", ""),
            "artist": "/".join(e.get("name", "") for e in info.get("singer", [])),
            "artistId": "/".join(
                e.get("name", "") for e in info.get("singer", [])
            ),  # 这里假设 artistId 应该是 singer 的 name，如果需要 singer 的 id 请修改
            "duration": info.get("interval", 0),
            "year": parse_time(info.get("time_public")),
            "trackNumber": info.get("index_album", 0),
            "cover": f"http://imgcache.qq.com/music/photo/album/{album_id % 100}/albumpic_{album_id}_0.jpg",
            "language": join_list(
                data["info"].get("lan", {}).get("content", []), "value"
            ),
            "genre": join_list(
                data["info"].get("genre", {}).get("content", []), "value"
            ),
            "album": info["album"].get("name", ""),
            "albumId": info["album"].get(
                "mid", ""
            ),  # 这里假设 albumId 应该是 album 的 mid，如果需要 album 的 name 请修改
        }

    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def get_kugou_meta(request: Request, item: dict):
    client = request.app.state.client
    try:
        params = {
            "type": 1,
            "page": "1",
            "albumid": item["album_id"],
            "timelength": 0,
            "srcappid": 2919,
            "clientver": 20000,
            "clienttime": current_time_millis,
            "mid": current_time_millis,
            "uuid": current_time_millis,
            "dfid": "-",
        }
        signature = signature_params(params)
        params = {**params, "signature": signature}
        response = await client.send(
            httpx.Request(
                "GET", "https://m3ws.kugou.com/api/v1/album/info", params=params
            )
        )

        album = response.json()

        return {
            "title": item["songname"],
            "artist": item["singername"],
            "artistId": item["singername"],
            "duration": item["duration"],
            "year": parse_time(album["data"]["publish_date"]),
            "cover": album["data"]["img400"],
            "language": item["trans_param"]["language"],
            "album": item["album_name"],
            "albumId": item["album_name"],
        }

    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def get_netebase_meta(request: Request, item: dict):
    try:
        title = item.get("name", "")
        artist = "/".join(e.get("name", "") for e in item.get("ar", []))
        artist_id = "/".join(e.get("name", "") for e in item.get("ar", []))
        duration = int(item.get("dt", 0)) // 1000
        publish_time = int(item.get("publishTime"))
        year = publish_time // 1000 if publish_time is not None else None
        album_name = item.get("al", {}).get("name", "")
        album_id = item.get("al", {}).get("name", "")
        cover = item.get("al", {}).get("picUrl", "")
        language = (
            item["al"]["tns"][0]["language"] if item.get("al", {}).get("tns") else None
        )

        return {
            "title": title,
            "artist": artist,
            "artistId": artist_id,
            "duration": duration,
            "year": year,
            "album": album_name,
            "albumId": album_id,
            "cover": cover,
            "language": language,
        }

    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def get_qq_lyric(request: Request, id: str, mid: str):
    client = request.app.state.client

    try:
        data = {
            "nobase64": 1,
            "format": "json",
            "musicid": id,
            "songmid": mid,
        }

        response = await client.send(
            httpx.Request(
                "GET",
                "https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg",
                params=data,
                headers={
                    "referer": "https://y.qq.com/",
                },
            )
        )

        res = response.json()
        return {
            "text": res.get("lyric", ""),
            "trans": res.get("trans", ""),
        }

    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def get_kugou_lyric(request: Request, hash: str):
    client = request.app.state.client
    try:

        def _decode_krc(krc: str) -> str:
            # 定义加密密钥
            enc_key = [
                0x40,
                0x47,
                0x61,
                0x77,
                0x5E,
                0x32,
                0x74,
                0x47,
                0x51,
                0x36,
                0x31,
                0x2D,
                0xCE,
                0xD2,
                0x6E,
                0x69,
            ]

            # 解码 Base64 并去掉前 4 个字节
            content_bytes = bytearray(base64.b64decode(krc)[4:])  # 转换为 bytearray

            # 使用异或解密
            for i in range(len(content_bytes)):
                content_bytes[i] ^= enc_key[i % 16]

            # 解压缩数据
            decompressed_bytes = zlib.decompress(content_bytes)

            # 将解压后的字节转换为字符串
            return decompressed_bytes.decode("utf-8")

        response = await client.send(
            httpx.Request(
                "GET",
                f"http://lyrics.kugou.com/search?hash={hash}",
            )
        )

        res = response.json()
        id = res["candidates"][0]["id"]
        accesskey = res["candidates"][0]["accesskey"]

        response = await client.send(
            httpx.Request(
                "GET",
                f"http://lyrics.kugou.com/download?ver=1&accesskey={accesskey}&id={id}",
            )
        )

        res = response.json()
        return {
            "ext": "krc",
            "text": _decode_krc(res.get("content", "")),
            "trans": res.get("trans", ""),
        }

    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def get_netebase_lyric(request: Request, id: str):
    client = request.app.state.client
    try:
        response = await client.send(
            httpx.Request(
                "GET",
                f"https://music.163.com/api/song/lyric?id={id}&lv=-1&kv=-1&tv=-1",
            )
        )

        res = response.json()
        return {
            "text": res.get("lrc", "").get("lyric"),
            "trans": res.get("tlyric", "").get("lyric"),
        }

    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def get_qq_scrape(request: Request):
    client = request.app.state.client
    try:
        params = dict(request.query_params)

        num_per_page = params.get("size", 4)
        page_num = params.get("page", 0)
        keyword = params.get("keyword")
        get_lyric = params.get("lyric", True)
        get_meta = params.get("meta", True)

        # 构建嵌套数据结构
        request_body = {
            "comm": {"mina": 1, "ct": 25},
            "req": {
                "method": "DoSearchForQQMusicMobile",
                "module": "music.search.SearchBrokerCgiServer",
                "param": {
                    "search_type": params.get("type", 0),  # 默认搜索类型 0
                    "query": keyword,  # 必须参数
                    "page_num": int(page_num),
                    "num_per_page": int(num_per_page),
                },
            },
        }

        encoded_data = json.dumps(request_body, ensure_ascii=False)

        query_params = {"data": encoded_data}

        # 发送 GET 请求
        response = await client.send(
            httpx.Request(
                "GET", "https://u.y.qq.com/cgi-bin/musicu.fcg", params=query_params
            )
        )

        # 返回 JSON 响应（可根据需要调整）
        res = response.json()
        items = res["req"]["data"]["body"]["item_song"]

        tasks = []
        for item in items:
            if check_name(item["name"], keyword):
                # 为每个有效项创建并行任务
                tasks.append(
                    get_qq_lyric(request, id=item["id"], mid=item["mid"])
                    if get_lyric == True
                    else retuen_null()
                )
                tasks.append(
                    get_qq_meta(request, item=item)
                    if get_meta == True
                    else retuen_null()
                )

        # 步骤2：批量执行所有异步任务
        all_results = await asyncio.gather(*tasks, return_exceptions=True)

        # 步骤3：重组结果数据
        maps = []
        for i in range(0, len(all_results), 2):  # 每两个结果为一组
            lyric_result = all_results[i]
            meta_result = all_results[i + 1] if i + 1 < len(all_results) else None

            # 过滤异常结果
            if not isinstance(lyric_result, Exception) and not isinstance(
                meta_result, Exception
            ):
                maps.append({"lyric": lyric_result, "meta": meta_result})

        return maps

    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def get_qq_album_meta(request: Request, item: map):
    client = request.app.state.client
    try:
        request_body = {
            "data": json.dumps(
                {
                    "otherAlbum": {
                        "module": "music.musichallAlbum.OtherAlbumList",
                        "method": "OtherAlbumList",
                        "param": {"albumMid": item["albumMid"], "order": 0, "num": 6},
                    },
                    "albumInfo": {
                        "module": "music.musichallAlbum.AlbumInfoServer",
                        "method": "GetAlbumDetail",
                        "param": {"albumMid": item["albumMid"]},
                    },
                    "albumSong": {
                        "module": "music.musichallAlbum.AlbumSongList",
                        "method": "GetAlbumSongList",
                        "param": {
                            "albumMid": item["albumMid"],
                            "begin": 0,
                            "num": 100,
                            "order": 2,
                        },
                    },
                    "collect": {
                        "module": "music.musicasset.AlbumFavRead",
                        "method": "IsAlbumFan",
                        "param": {"v_albumMid": [item["albumMid"]]},
                    },
                    "comm": {
                        "g_tk": 709041629,
                        "uin": "0",
                        "format": "json",
                        "ct": 20,
                        "cv": 1803,
                        "platform": "wk_v17",
                    },
                },
                ensure_ascii=False,
            )
        }
        response = await client.send(
            httpx.Request(
                "GET", "https://u.y.qq.com/cgi-bin/musicu.fcg", params=request_body
            )
        )

        # 返回 JSON 响应（可根据需要调整）
        info = response.json()
        return {
            "id": info["albumInfo"]["data"]["basicInfo"]["albumMid"],
            "album": info["albumInfo"]["data"]["basicInfo"]["albumName"],
            "artist": "/".join(
                [e["name"] for e in info["albumInfo"]["data"]["singer"]["singerList"]]
            ),
            "year": parse_time(info["albumInfo"]["data"]["basicInfo"]["publishDate"]),
            "cover": f"http://imgcache.qq.com/music/photo/album/{info['albumInfo']['data']['basicInfo']['albumID'] % 100}/albumpic_{info['albumInfo']['data']['basicInfo']['albumID']}_0.jpg",
            "songs": [
                {
                    "title": e["songInfo"]["title"],
                    "duration": e["songInfo"]["interval"],
                    "language": info["albumInfo"]["data"]["basicInfo"]["language"],
                    "genre": info["albumInfo"]["data"]["basicInfo"]["genre"],
                }
                for e in info["albumSong"]["data"]["songList"]
            ],
        }

        # items = res["req"]["data"]["body"]["singer"]
    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def get_qq_artist_scrape(request: Request):
    client = request.app.state.client
    try:

        params = dict(request.query_params)

        num_per_page = params.get("size", 4)
        page_num = params.get("page", 0)
        keyword = params.get("keyword")

        # 构建嵌套数据结构
        request_body = {
            "comm": {"mina": 1, "ct": 25},
            "req": {
                "method": "DoSearchForQQMusicMobile",
                "module": "music.search.SearchBrokerCgiServer",
                "param": {
                    "search_type": 1,  # 默认搜索类型 0
                    "query": keyword,  # 必须参数
                    "page_num": int(page_num),
                    "num_per_page": int(num_per_page),
                },
            },
        }

        encoded_data = json.dumps(request_body, ensure_ascii=False)

        query_params = {"data": encoded_data}

        # 发送 GET 请求
        response = await client.send(
            httpx.Request(
                "GET", "https://u.y.qq.com/cgi-bin/musicu.fcg", params=query_params
            )
        )

        # 返回 JSON 响应（可根据需要调整）
        res = response.json()

        items = res["req"]["data"]["body"]["singer"]

        item = items[0]
        request_body = {
            "comm": {"cv": 0, "ct": 24},
            "albumList": {
                "method": "GetAlbumList",
                "module": "music.musichallAlbum.AlbumListServer",
                "param": {
                    "singerMid": item["singerMID"],
                    "order": 0,
                    "begin": 0,
                    "num": item["albumNum"],
                    "songNumTag": 0,
                    "singerID": 0,
                },
            },
        }
        query_params = {"data": json.dumps(request_body, ensure_ascii=False)}
        # 发送 GET 请求
        response = await client.send(
            httpx.Request(
                "GET",
                "https://u.y.qq.com/cgi-bin/musicu.fcg",
                params=query_params,
            )
        )
        res = response.json()

        items = res["albumList"]["data"]["albumList"]
        tasks = [get_qq_album_meta(request, item=item) for item in items]
        # 步骤2：批量执行所有异步任务
        all_results = await asyncio.gather(*tasks, return_exceptions=True)
        return all_results

    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def get_kugou_scrape(request: Request):
    client = request.app.state.client
    try:
        params = dict(request.query_params)
        num_per_page = params.get("size", 4)
        page_num = params.get("page", 0)
        keyword = params.get("keyword")
        get_lyric = params.get("lyric", True)
        get_meta = params.get("meta", True)

        query_params = {"page": page_num, "pagesize": num_per_page, "keyword": keyword}

        # 发送 GET 请求
        response = await client.get(
            "http://mobilecdnbj.kugou.com/api/v3/search/song", params=query_params
        )

        # 返回 JSON 响应（可根据需要调整）
        res = response.json()
        items = res["data"]["info"]

        tasks = []
        for item in items:
            if check_name(item["songname"], keyword):
                # 为每个有效项创建并行任务
                tasks.append(
                    get_kugou_lyric(request, hash=item["hash"])
                    if get_lyric == True
                    else retuen_null()
                )
                tasks.append(
                    get_kugou_meta(request, item=item)
                    if get_meta == True
                    else retuen_null()
                )

        # 步骤2：批量执行所有异步任务
        all_results = await asyncio.gather(*tasks, return_exceptions=True)

        # 步骤3：重组结果数据
        maps = []
        for i in range(0, len(all_results), 2):  # 每两个结果为一组
            lyric_result = all_results[i]
            meta_result = all_results[i + 1] if i + 1 < len(all_results) else None

            # 过滤异常结果
            if not isinstance(lyric_result, Exception) and not isinstance(
                meta_result, Exception
            ):
                maps.append({"lyric": lyric_result, "meta": meta_result})

        return maps

    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def get_kugou_album_meta(request: Request, item: map):
    client = request.app.state.client
    try:
        # 定义签名生成函数
        def signature_params(params):
            # 按键排序并拼接参数
            sorted_params = sorted(params.items(), key=lambda x: x[0])
            data = "".join(f"{k}={v}" for k, v in sorted_params)

            # 定义密钥
            secret = "NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt"

            # 计算 MD5 签名
            signature = (
                hashlib.md5(f"{secret}{data}{secret}".encode("utf-8"))
                .hexdigest()
                .upper()
            )
            return signature

        # 构造请求参数
        current_time = current_time_millis  # 当前时间戳（毫秒）
        request_body = {
            "type": 1,
            "page": 1,
            "albumid": item.get("albumid"),
            "timelength": 0,
            "srcappid": 2919,
            "clientver": 20000,
            "clienttime": current_time,
            "mid": current_time,
            "uuid": current_time,
            "dfid": "-",
        }

        # 生成签名并添加到参数中
        signature = signature_params(request_body)
        request_body["signature"] = signature

        # 发起 GET 请求
        url = "https://m3ws.kugou.com/api/v1/album/info"
        query_string = urlencode(request_body)
        full_url = f"{url}?{query_string}"

        # 假设 _get 是一个异步函数，用于发起 HTTP 请求
        # return await _get(full_url, params=data, cookie=cookie)
        response = await client.send(httpx.Request("GET", full_url))

        # 返回 JSON 响应（可根据需要调整）
        info = response.json()
        return {
            "id": info["data"]["albumname"],
            "album": info["data"]["albumname"],
            "artist": info["data"]["singer"],
            "year": parse_time(info["data"]["publish_date"]),
            "cover": info["data"]["img400"],
            "songs": [
                {
                    "title": e["songname"].split(" - ")[-1],
                    "duration": e["timelength"],
                    "language": e["trans_param"]["language"],
                }
                for e in info["data"]["list"]
            ],
        }

    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def get_kugou_artist_scrape(request: Request):
    client = request.app.state.client
    try:

        params = dict(request.query_params)

        num_per_page = params.get("size", 4)
        page_num = params.get("page", 1)
        keyword = params.get("keyword")

        # 构建嵌套数据结构
        request_body = {
            "keyword": keyword,
            "page": page_num,
            "pagesize": num_per_page,
        }

        encoded_data = json.dumps(request_body, ensure_ascii=False)

        # 发送 GET 请求
        response = await client.send(
            httpx.Request(
                "GET",
                "http://mobilecdnbj.kugou.com/api/v3/search/singer",
                params=request_body,
            )
        )

        # 返回 JSON 响应（可根据需要调整）
        res = response.json()

        items = res["data"]

        item = items[0]
        request_body = {
            "singerid": item["singerid"],
            "page": page_num,
            "pagesize": 100,
        }

        # 发送 GET 请求
        response = await client.send(
            httpx.Request(
                "GET",
                "http://mobilecdnbj.kugou.com/api/v3/singer/album",
                params=request_body,
            )
        )
        res = response.json()

        items = res["data"]["info"]
        tasks = [get_kugou_album_meta(request, item=item) for item in items]
        # 步骤2：批量执行所有异步任务
        all_results = await asyncio.gather(*tasks, return_exceptions=True)
        return all_results

    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def get_netebase_scrape(request: Request):
    client = request.app.state.client
    try:
        params = dict(request.query_params)
        num_per_page = params.get("size", 4)
        page_num = int(params.get("page", 1)) > 0 and int(params.get("page", 1)) or 1
        keyword = params.get("keyword")
        get_lyric = params.get("lyric", True)
        get_meta = params.get("meta", True)

        query_params = {
            "limit": num_per_page,
            "offset": (page_num - 1) * num_per_page,
            "s": keyword,
            "type": 1,
        }

        # 发送 GET 请求
        response = await client.get(
            "https://music.163.com/api/cloudsearch/pc", params=query_params
        )

        # 返回 JSON 响应（可根据需要调整）
        res = response.json()
        items = res["result"]["songs"]

        tasks = []
        for item in items:
            if check_name(item["name"], keyword):
                # 为每个有效项创建并行任务
                tasks.append(
                    get_netebase_lyric(request, id=item["id"])
                    if get_lyric == True
                    else retuen_null()
                )
                tasks.append(
                    get_netebase_meta(request, item=item)
                    if get_meta == True
                    else retuen_null()
                )

        # 步骤2：批量执行所有异步任务
        all_results = await asyncio.gather(*tasks, return_exceptions=True)

        # 步骤3：重组结果数据
        maps = []
        for i in range(0, len(all_results), 2):  # 每两个结果为一组
            lyric_result = all_results[i]
            meta_result = all_results[i + 1] if i + 1 < len(all_results) else None

            # 过滤异常结果
            if not isinstance(lyric_result, Exception) and not isinstance(
                meta_result, Exception
            ):
                maps.append({"lyric": lyric_result, "meta": meta_result})

        return maps

    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def scrape_artists(request: Request):
    try:
        tasks = [
            get_qq_artist_scrape(request=request),
            get_kugou_artist_scrape(request=request),
        ]
        # 步骤2：批量执行所有异步任务
        all_results = await asyncio.gather(*tasks, return_exceptions=True)
        flattened_results = [
            item
            for res in all_results
            if not isinstance(res, Exception)
            for item in (res if isinstance(res, list) else [res])
        ]

        return flattened_results

    except httpx.HTTPStatusError as e:
        return {"error": str(e)}, e.response.status_code
    except Exception as e:
        log(f"报错:{str(e)}")
        return {"error": str(e)}, 500


async def get_scrape(request: Request):
    results = await asyncio.gather(
        get_qq_scrape(request),
        get_kugou_scrape(request),
        get_netebase_scrape(request),
        return_exceptions=True,
    )

    # 使用列表推导式展开
    flattened_results = [
        item
        for res in results
        if not isinstance(res, Exception)
        for item in (res if isinstance(res, list) else [res])
    ]

    return flattened_results


# 获取单个播放列表详情
async def get_playlist_detail(client, id):
    url = f"https://music.163.com/api/v1/playlist/detail"
    params = {"id": id, "n": 100, "timestamp": get_timestamp()}
    headers = {"User-Agent": get_user_agent(), "Referer": "https://music.163.com"}
    try:
        response = await client.get(url, params=params, headers=headers)
        if response.status_code == 200:
            res = response.json()
            if "playlist" in res:
                songs = res["playlist"]["tracks"]
                return {"id": id + neteStartIndex, "songs": songs}
            else:
                log(res.get("message", "No playlist found"))
        else:
            log(f"Failed to fetch playlist {id}: {response.status_code}")
    except Exception as e:
        log(f"Error fetching playlist {id}: {e}")


# 获取 popular 方法
async def get_popular(request: Request):
    playlistsIds = [
        2859214503,  # 一周欧美上新
        2829816518,  # 欧美私人订制
        5327906368,  # 乐迷雷达
        5362359247,  # 宝藏雷达
        3136952023,  # 私人雷达
        60198,  # Billboard 排行榜
        180106,  # UK 排行榜
        5212729721,  # 欧美点唱机
        2724708415,  # 私藏推荐精选
        5300458264,  # 新歌雷达
        7463185187,  # 开发者夹带私货
    ]
    client = request.app.state.client  # 使用共享客户端
    tasks = [get_playlist_detail(client, id) for id in playlistsIds]
    results = await asyncio.gather(*tasks)
    popular_songs = [songs for songs in results if songs is not None]

    return {"data": popular_songs}
